import { BehaviorSubject, Subscription, pairwise, filter, take, distinct, distinctUntilChanged } from 'rxjs';
import { _decorator } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('ReactiveProperty')
export class ReactiveProperty<T> {

    static Create<T>(value: T): ReactiveProperty<T> {
        return new ReactiveProperty<T>().init(value);
    }

    _subject: BehaviorSubject<T> = null;

    init(value: T): ReactiveProperty<T> {
        this._subject = new BehaviorSubject<T>(value);
        return this;
    }

    get value(): T {
        return this._subject.value;
    }

    set value(value: T) {
        this._subject.next(value);
    }

    subscribe(callback: (value: T) => void): Subscription {
        return this._subject.subscribe(callback);
    }

    subscribeUntilChanged(callback: (value: T) => void): Subscription {
        return this._subject.pipe(distinctUntilChanged()).subscribe(callback);
    }

    subscribePairWise(callback: (pair: T[]) => void): Subscription {
        return this._subject.pipe(pairwise()).subscribe(callback);
    }

    /** 判断条件为真，直接成功或等待成功 */
    subscribeOnceIf(condition: (value: T) => boolean, callback: (value: T) => void): Subscription {
        return this._subject.pipe(filter(_ => { return condition(_); }), take(1)).subscribe(callback);
    }

    whenTrueOnce() {
        return this._subject.pipe(filter(_ => !!_), take(1));
    }

    whenFalseOnce() {
        return this._subject.pipe(filter(_ => !_), take(1));
    }

    whenTrue() {
        return this._subject.pipe(filter(_ => !!_));
    }

    subscribeWhenTrue(callback: () => void): Subscription {
        return this.whenTrueOnce().subscribe(callback);
    }

    again() {
        this._subject.next(this.value);
    }
}